var deasync = require('deasync');
var ObjectID = require('mongodb').ObjectID;
var util = require('./utils/util');

function mongo_server(entity) {
	this.base_config = entity;
	this.entity = new entity.entity();
	this.col = entity.mongo.collection;
}

mongo_server.prototype.searchById = function (id, callback) {
	this.col.findOne({_id: new ObjectID(id)}, function (err, docs) {
		let result = null;
		if (!err){
			result = docs;
			result._id = result._id.toString();
		}
		callback(result);
	});
};

mongo_server.prototype.searchOne = function(query, callback){
	this.col.findOne(query, function (err, docs) {
		let result = null;
		if (!err){
			result = docs;
			result._id = result._id.toString();
		}
		callback(result);
	});
};

mongo_server.prototype.search = function(query, callback){
	this.col.find(query).toArray(function (err, docs) {
		let result = null;
		if (!err && docs.length > 0){
			result = docs;
			for (let i = 0; i < docs.length; i++)
				result[i]._id = result[i]._id.toString();
		}
		callback(result);
	});
};

function addProperty(obj) {
	let md5 = util.string.toMd5(JSON.stringify(obj));
	obj.cnynld_hashcode = md5;
	if (obj.cnynld_create_time){
		obj.cnynld_version++;
		obj.cnynld_update_time = new Date().getTime();
	}
	else{
		obj.cnynld_create_time = new Date().getTime();
		obj.cnynld_version = 1;
	}
	return obj;
}
mongo_server.prototype.save = function (data, callback, vali_hash, vali_version) {
	let self = this;
	let current = util.object.clone(data);
	for (let key in current){
		if (this.entity[key] == undefined || typeof current[key] === 'function') {
			if (key == "_id") continue;
			delete current[key];
		}
	}
	if (current._id) current._id = new ObjectID(current._id);
	current = addProperty(current);
	self.col.save(current, function (err, docs) {
		let result = null;
		if (!err && docs.result.ok == 1){
			result = current;
			result._id = result._id.toString();
		}
		callback(result);
	});
};

mongo_server.prototype.remove = function(query, callback){
	this.col.remove(query, function (err, data) {
		callback(err ? false : true);
	});
};

mongo_server.prototype.removeById = function(id, callback){
	this.col.remove({ _id: id}, function (err, data) {
		callback(err ? false : true);
	});
};

/**
 *  2016年10月26日 add...
 */

mongo_server.prototype.count = function (query, callback) {
	this.col.count(query, function (err, count) {
		callback(err ? -1: count);
	});
};


function get_page_cursor(self, query, callback) {
	
	let cursor = self.col.find(query.query);
	query.sort && cursor.sort(query.sort);
	
	let page = (query.page - 1) * query.size;
	if (query.page > query.total) {
		callback(query);
		return;
	}
	
	cursor.skip(page).limit(query.size).toArray(function (err, docs) {
		let result = query;
		if (!err && docs.length > 0){
			docs.forEach((doc) => {
				doc._id = doc._id.toString();
				result.data.push(doc);
			});
		}
		callback(result);
	});
}

mongo_server.prototype.page = function (custom_query, callback) {
	//let def = { query: {}, sort: {}, total: 0, page: 1, size: 50};
	let self = this;
	let query = Object.assign({}, custom_query);
	query.query = query.query || {};
	query.page = query.page || 1;
	query.size = query.size || 50;
	query.data = [];
	if (!query.total || query.total == 0){
		this.count(query.query, function (size) {
			if (size == -1) callback(null);
			query.total = size;
			get_page_cursor(self, query, callback);
		});
	}else get_page_cursor(self, query, callback);
};

module.exports = mongo_server;